<?php

/**
 * 币种文章Redis
 * @App	
 * @Group 
 * @Action CoinArticleRedis
 * @author lilei
 * @date 2018年5月25日
 *
 */
namespace app\common\redis;
use app\common\library\CommonFun;
use app\common\model\article\PublishArticleCoinModel;
use app\common\model\article\PublishArticleModel;
use app\common\model\article\PublishCoinArticleViewModel;
use app\common\model\article\PublishWeiboModel;
use app\common\model\CommonModel;

class CoinArticleRedis extends RedisModel {
	/**
	 * Redis配置名称
	 * @var string
	 */
	public $redis = 'default';
	
	/**
	 * Redis key
	 * @var string
	 */
	public $key = '';
	
	/**
	 * Redis key 前缀
	 */
	public $key_prefix = 'coin_article';
	
	/**
	 * 创建币种文章ID集合
	 * @param int $coin_id 币种编号
	 * @param int $limit 数量限制 0 不限制
	 */
	public function createCoinArticleList( $coin_id, $limit=500 ) {
		// 获取coin相关文章列表
		$modelArticle = new PublishArticleModel();
		$modelArtCoin = new PublishArticleCoinModel();
		$map = array(
				'is_published' => 1,
				'status' => 1,
				'deleted' => -1,
				'is_tmp' => -1,
		);
		$article_id_list = [];
		// 币种文章
		$coin_art_list = $modelArtCoin->get_coin_article_list($coin_id);
		// 存在币种文章
		if ( $coin_art_list ) {
			$map['id'] = array('in',$coin_art_list);
			$article_id_list = $modelArticle->search_id_list($map, 1, false, 'create_time', $limit);
		}
		
		$this->SetRedisKey($coin_id);
		if ( $this->ExistsKey() ) {
			$this->Delete();
		}
		if ($article_id_list) {
			
			$this->PipeStart();
			foreach ( $article_id_list as $item ) {
				if ( !$item ) {
					continue;
				}
				$this->ListRpush($item);
			}
			$this->PipeExec();
		}
	}
	
	/**
	 * 获取币种相关文章ID集合
	 * @param int $coin_id 币种编号
	 * @param number $start 开始位置
	 * @param number $end 结束位置 -1为全部
	 * @return array
	 */
	public function GetCoinArticleList( $coin_id, $start=0, $end=-1 ) {
		$this->SetRedisKey($coin_id);
		$res = $this->ListlRange($start, $end);
		return $res;
	}
	
	/**
	 * 获取一条币种相关文章
	 * @param int $coin_id 币种编号
	 * @param number $index 位置
	 * @return mixed
	 */
	public function GetCoinOneArticle( $coin_id, $index=0 ) {
		$this->SetRedisKey($coin_id);
		$res = $this->ListlGet($index);
		return $res;
	}
	
	/**
	 * 创建币种微博ID集合
	 * @param int $coin_id 币种编号
	 * @param int $limit 数量限制 0 不限制
	 */
	public function createCoinWeiboList( $coin_id, $limit=100 ) {
		// 获取相关微博列表
		$modelWeibo = new PublishWeiboModel();
		$map = array(
				'status' => 3, // 已通过
				'publish_status' => 2, //已发布
		);
		$map['_string'] = CommonModel::search_json_array($coin_id, 'coin_list');
		$weibo_id_list = $modelWeibo->search_id_list($map, 1, false, 'create_time', $limit);
		$key = "{$coin_id}:weibo_list";
		$this->SetRedisKey( $key );
		if ( $this->ExistsKey() ) {
			$this->Delete();
		}
		if ( $weibo_id_list ) {
			$this->PipeStart();
			foreach ( $weibo_id_list as $item ) {
				if ( !$item ) {
					continue;
				}
				$this->ListRpush($item);
			}
			$this->PipeExec();
		}
	}
	
	/**
	 * 获取币种相关微博ID集合
	 * @param int $coin_id 币种编号
	 * @param number $start 开始位置
	 * @param number $end 结束位置 -1为全部
	 * @return array
	 */
	public function GetCoinWeiboList( $coin_id, $start=0, $end=-1 ) {
		$key = "{$coin_id}:weibo_list";
		$this->SetRedisKey($key);
		$res = $this->ListlRange($start, $end);
		return $res;
	}
	
	/**
	 * 获取一条币种相关微博
	 * @param int $coin_id 币种编号
	 * @param number $index 位置
	 * @return mixed
	 */
	public function GetCoinOneWeibo( $coin_id, $index=0 ) {
		$key = "{$coin_id}:weibo_list";
		$this->SetRedisKey($key);
		$res = $this->ListlGet($index);
		return $res;
	}
	
	/**
	 * 创建币相关所有类型文章集合 (sort set)
	 * @param int 	$coin_id	币种编号
	 */
	public function CreateCoinAllTypeArticle(  $coin_id ) {
		// 币种相关文章ID列表
		$coinArticleList = $this->GetCoinArticleList($coin_id);
		$articleDataList = [];
		if ( $coinArticleList ) {
			$modelArticle = new PublishArticleModel();
			$articleDataList = $modelArticle->muti_get_data_by_id_list($coinArticleList, true,true, false);
		}
		// 币种相关微博ID列表
		$coinWeiboList = $this->GetCoinWeiboList($coin_id);
		$weiboDataList = [];
		if ( $coinWeiboList ) {
			$modelWeibo = new PublishWeiboModel();
			$weiboDataList = $modelWeibo->muti_get_data_by_id_list($coinWeiboList);
		}
		
		// 向有序集合中添加数据
		$item_score = [];
		if ( $articleDataList ) {
			foreach ( $articleDataList as $v ) {
				$item_score[ 'article_'.$v['id'] ] = strtotime($v['create_time']);
			}
			
		}
		if ( $weiboDataList ) {
			foreach ( $weiboDataList as $v ) {
				$item_score[ 'weibo_'.$v['id'] ] = strtotime($v['create_time']);
			}
		}
		$key = "{$coin_id}:CoinAllTypeArticle";
		$this->SetRedisKey($key);
		if ( $this->ExistsKey() ) {
			$this->Delete();
		}
		$item_score && $this->SortSetZmadd($item_score);
	}
	
	/**
	 * 获取币相关所有类型文章集合
	 * @param int $coin_id 币种编号
	 * @param int $start
	 * @param int $end
	 * @return array
	 */
	public function GetCoinAllTypeArticle( $coin_id, $start=0, $end=-1 ) {
		$key = "{$coin_id}:CoinAllTypeArticle";
		$this->SetRedisKey($key);
		$res = $this->SortSetZRevRange( $start, $end );
		return $res?:array();
	}
	
	/**
	 * 根据条件获取币相关所有类型文章集合
	 * @param int $coin_id
	 * @param int $startTimestamp
	 * @param int $endTimestamp
	 * @param number $start
	 * @param number $end
	 * @param bool $is_assoc
	 * @return array
	 */
	public function GetCoinAllTypeArticleByCreateTime( $coin_id, $startTimestamp, $endTimestamp,  $start=0, $end=-1,  $is_assoc=false ) {
		$key = "{$coin_id}:CoinAllTypeArticle";
		$this->SetRedisKey($key);
		$res = $this->SrotSetZRevRangeByScore( $startTimestamp, $endTimestamp, $start, $end, $is_assoc ) ;
		return $res?:array();
	}
	
	/**
	 * 获取币相关所有类型文章集合元素个数
	 * @param int $coin_id 币种编号
	 */
	public function CountCoinAllTypeArticle( $coin_id ) {
		$key = "{$coin_id}:CoinAllTypeArticle";
		$this->SetRedisKey($key);
		$res = $this->SortSetSize();
		return $res?:0;
	}
	
	/**
	 * 创建非币相关所有类型文章集合 (sort set)
	 */
	public function CreateNoCoinAllTypeArticle () {
		// 获取文章
		$modelArticle = new PublishArticleModel();
		$alimit = 100;
		
		$map = array(
				'is_published' => 1,
				'status' => 1,
				'deleted' => -1,
				'coin_list' => array("eq", "[]"),
				'is_tmp' => -1,
		);
		$article_id_list = $modelArticle->search_id_list($map, 1, false, 'create_time', $alimit);
		$articleDataList = [];
		if ( $article_id_list ) {
			$articleDataList = $modelArticle->muti_get_data_by_id_list($article_id_list, true, true ,false);
		}
		// 获取微博
		$modelWeibo = new PublishWeiboModel();
		
		$map = array(
				'status' => 3, // 已通过
				'publish_status' => 2, //已发布
				'coin_list' => array("eq", "[]"),
		);
		$weibo_id_list = $modelWeibo->search_id_list($map, 1, false, 'create_time', $alimit);
		$weiboDataList = [];
		if ( $weibo_id_list ) {
			$weiboDataList = $modelWeibo->muti_get_data_by_id_list($weibo_id_list);
		}
		// 向有序集合中添加数据
		$item_score = [];
		if ( $articleDataList ) {
			foreach ( $articleDataList as $v ) {
				$item_score[ 'article_'.$v['id'] ] = strtotime($v['create_time']);
			}
			
		}
		if ( $weiboDataList ) {
			foreach ( $weiboDataList as $v ) {
				$item_score[ 'weibo_'.$v['id'] ] = strtotime($v['create_time']);
			}
		}
		$key = ":NoCoinAllTypeArticle";
		$this->SetRedisKey($key);
		if ( $this->ExistsKey() ) {
			$this->Delete();
		}
		$item_score && $this->SortSetZmadd($item_score);
	}
	
	/**
	 * 获取非币相关所有类型文章集合
	 * @return array
	 */
	public function GetNoCoinAllTypeArticle(  $start=0, $end=-1 ) {
		$key = ":NoCoinAllTypeArticle";
		$this->SetRedisKey($key);
		$res = $this->SortSetZRevRange(  $start, $end );
		return $res?:array();
	}
	
	
	//-----------------------------------------------每日币种相关文章-----------------------------------------------------//
	
	/**
	 * 构建每日币种相关文章集合
	 * @param array|int $coin_id_set	币种设置
	 * @param int		$is_feed			是否是Feed流文章	1:是  -1:否  0:全部
	 * @param int		$is_time		是否是时效性文章	1:是  -1:否  0:全部
	 * @param string 	$startDateTime	开始时间DateTime
	 * 
	 * @return bool
	 */
	public function createDateCoinArticleList( $coin_id_set, $is_feed, $is_time, $startDateTime) {
		if ( !$coin_id_set ) CommonFun::make_exception("构建每日币种相关文章集合币种设置错误", false);
		if ( is_numeric($startDateTime) ) {
			$endDateTime = date( "Y-m-d 00:00:00", $startDateTime+86400 );
			$startDateTime = date( "Y-m-d 00:00:00", $startDateTime );
		}else {
			$startDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime) );
			$endDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime)+86400 );
		}
		if ( !$startDateTime || !$endDateTime ) CommonFun::make_exception("构建每日币种相关文章集合开始时间错误", false);
		
		// 币种相关文章视图模型
		$coinArticleModel = new PublishCoinArticleViewModel();
		// 查找数据
		$map = [
				'create_time' => array( 'between', array( $startDateTime, $endDateTime ) ),
		];
		if ( $is_time != 0 ) {
			$map['is_time'] = $is_time;
		}
		if ( $is_feed !=0 ) {
			$map['is_feed'] = $is_feed;
		}
		
		is_array($coin_id_set) ? $map['coin_id'] = array( 'in', $coin_id_set ) : $map['coin_id'] = $coin_id_set;
		$article_list = $coinArticleModel->field('coin_id, article_id')->where($map)->select();
		if ( !$article_list ) {
			return false;
		}
		$coinArticleList = [];
		foreach ( $article_list as $v ) {
			$coinArticleList[$v['coin_id']][] = $v['article_id'];
		}
		// 构建key
		$keyPre = ":DateCoinArticleList:";
		$startDateTime = str_replace([':',' ','-','000000'], '', $startDateTime);
		$endDateTime = str_replace([':',' ','-','000000'], '', $endDateTime);
		$keySuf = "{$startDateTime}-{$endDateTime}:{$is_time}:{$is_feed}:";
		$keyMain = $keyPre.$keySuf;
		// 存入Redis 
		foreach ( $coinArticleList as $coin_id => $_v ) {
			$key = $keyMain.$coin_id;
			$this->SetRedisKey($key);
			if ( $this->ExistsKey() ) {
				$this->Delete();
			}
			$_v = array_unique($_v);
			$this->SetMutiSadd($_v);
		}
		return true;
	}
	
	/**
	 * 向每日币种相关文章集合增加文章
	 * @param array|int $coin_id_set	币种设置
	 * @param string 	$startDateTime	开始时间DateTime
	 * @param int		$is_feed			是否是Feed流文章	1:是  -1:否  0:全部
	 * @param int		$is_time		是否是时效性文章	1:是  -1:否  0:全部
	 * @param array|int $article_id_set	文章编号设置
	 * @return bool
	 */
	public function pushDateCoinArticleList ( $coin_id_set, $is_feed, $is_time, $startDateTime, $article_id_set ) {
		if ( !$coin_id_set ) CommonFun::make_exception("构建每日币种相关文章集合币种设置错误", false);
		if ( is_numeric($startDateTime) ) {
			$endDateTime = date( "Y-m-d 00:00:00", $startDateTime+86400 );
			$startDateTime = date( "Y-m-d 00:00:00", $startDateTime );
		}else {
			$startDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime) );
			$endDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime)+86400 );
		}
		if ( !$startDateTime || !$endDateTime ) CommonFun::make_exception("构建每日币种相关文章集合开始时间错误", false);
		// 判断币种设置是数组还是单个
		$coin_list = is_array($coin_id_set) ? array_unique($coin_id_set) : array($coin_id_set);
		// 判断文章设置是数组还是单个
		$article_list = is_array( $article_id_set ) ? array_unique($article_id_set) : array($article_id_set);
		// 构建key
		$keyPre = ":DateCoinArticleList:";
		$startDateTime = str_replace([':',' ','-','000000'], '', $startDateTime);
		$endDateTime = str_replace([':',' ','-','000000'], '', $endDateTime);
		$keySuf = "{$startDateTime}-{$endDateTime}:{$is_time}:{$is_feed}:";
		$keyMain = $keyPre.$keySuf;
		// 构建数据
		foreach ( $coin_list as $coin_id ) {
			$key = $keyMain.$coin_id;
			$this->SetRedisKey($key);
			$this->SetMutiSadd($article_list);
		}
		return true;
	}
	
	/**
	 * 移除每日币种相关文章集合中指定文章
	 * @param array|int $coin_id_set	币种设置
	 * @param string 	$startDateTime	开始时间DateTime
	 * @param int		$is_feed			是否是Feed流文章	1:是  -1:否  0:全部
	 * @param int		$is_time		是否是时效性文章 1:是 -1:否  0:全部
	 * @param array|int $article_id_set	文章编号设置
	 * @return bool
	 */
	public function removeDateCoinArticleList( $coin_id_set, $is_feed, $is_time, $startDateTime, $article_id_set ) {
		if ( !$coin_id_set ) CommonFun::make_exception("移除每日币种相关文章集合中指定文章, 币种设置错误", false);
		if ( is_numeric($startDateTime) ) {
			$endDateTime = date( "Y-m-d 00:00:00", $startDateTime+86400 );
			$startDateTime = date( "Y-m-d 00:00:00", $startDateTime );
		}else {
			$startDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime) );
			$endDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime)+86400 );
		}
		if ( !$startDateTime || !$endDateTime ) CommonFun::make_exception("移除每日币种相关文章集合中指定文章, 开始时间错误", false);
		// 判断币种设置是数组还是单个
		$coin_list = is_array($coin_id_set) ? array_unique($coin_id_set) : array($coin_id_set);
		// 判断文章设置是数组还是单个
		$article_list = is_array( $article_id_set ) ? array_unique($article_id_set) : array($article_id_set);
		// 构建key
		$keyPre = ":DateCoinArticleList:";
		$startDateTime = str_replace([':',' ','-','000000'], '', $startDateTime);
		$endDateTime = str_replace([':',' ','-','000000'], '', $endDateTime);
		$keySuf = "{$startDateTime}-{$endDateTime}:{$is_time}:{$is_feed}:";
		$keyMain = $keyPre.$keySuf;
		// 构建数据
		foreach ( $coin_list as $coin_id ) {
			$key = $keyMain.$coin_id;
			$this->SetRedisKey($key);
			$this->SetRem($article_list);
		}
		return true;
	}
	
	/**
	 * 移除全部状态每日币种相关文章集合中指定文章
	 * @param array|int $coin_id_set	币种设置
	 * @param string 	$startDateTime	开始时间DateTime
	 * @param array|int $article_id_set	文章编号设置
	 * @return bool
	 */
	public function removeAllStatusDateCoinArticleList( $coin_id_set, $startDateTime, $article_id_set ) {
		if ( !$coin_id_set ) CommonFun::make_exception("移除全部状态每日币种相关文章集合中指定文章, 币种设置错误", false);
		$is_feed_set = [ -1, 0, 1 ];
		$is_time_set = [ -1, 0, 1 ];
		foreach ( $is_feed_set as $is_feed ) {
			foreach ( $is_time_set as $is_time ) {
				$this->removeDateCoinArticleList($coin_id_set, $is_feed, $is_time, $startDateTime, $article_id_set);
			}
		}
		return true;
	}
	
	/**
	 * 获取每日币种相关文章集合
	 * @param array|int $coin_id_set	币种设置
	 * @param int		$is_feed			是否是Feed流文章	1:是  -1:否  0:全部
	 * @param int		$is_time		是否是时效性文章 1:是 -1:否  0:全部
	 * @param string 	$startDateTime	开始时间DateTime
	 * @param int 		$offsetDay		时间跨度, 整型天数
	 * @return array
	 */
	public function getDateCoinArticleList ( $coin_id_set, $is_feed, $is_time, $startDateTime, $offsetDay ) {
		if ( !$coin_id_set ) CommonFun::make_exception("获取每日币种相关文章集合币种设置错误", false);
		if ( !is_int($offsetDay) || !$offsetDay || $offsetDay<0 ) {
			CommonFun::make_exception("获取每日币种相关文章集合时间跨度参数错误", false);
		}
		if ( is_numeric($startDateTime) ) {
			$endDateTime = date( "Y-m-d 00:00:00", $startDateTime+(86400*$offsetDay) );
			$startDateTime = date( "Y-m-d 00:00:00", $startDateTime );
		}else {
			$startDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime) );
			$endDateTime = date( "Y-m-d 00:00:00", strtotime($startDateTime)+(86400*$offsetDay) );
		}
		if ( !$startDateTime || !$endDateTime ) CommonFun::make_exception("获取每日币种相关文章集合开始时间错误", false);
		
		// key前缀
		$keyPre = ":DateCoinArticleList:";
		
		// 判断币种设置是数组还是单个
		$coin_list = is_array($coin_id_set) ? array_unique($coin_id_set) : array($coin_id_set);
		// 币种相关文章
		$coinArticleList = [];
		
		// 判断是一天还是多天
		if ( $offsetDay == 1 ) {
			$startDateTime = str_replace([':',' ','-','000000'], '', $startDateTime);
			$endDateTime = str_replace([':',' ','-','000000'], '', $endDateTime);
			$keySuf = "{$startDateTime}-{$endDateTime}:{$is_time}:{$is_feed}:";
			$keyMain = $keyPre.$keySuf;
			foreach ( $coin_list as $coin_id ) {
				$key = $keyMain.$coin_id;
				$this->SetRedisKey($key);
				$article_list = $this->SetGetAll();
				$coinArticleList[$coin_id] = array_unique($article_list) ?:[];
			}
		}else {
			// 生成时间段
			$timeList = range(strtotime($startDateTime), strtotime($endDateTime), 86400);
			$time_group = [];
			foreach ($timeList as $value) {
				$s = date( "Y-m-d 00:00:00", $value );
				$e = date( "Y-m-d 00:00:00", $value+86400 );
				$s = str_replace([':',' ','-','000000'], '', $s);
				$e = str_replace([':',' ','-','000000'], '', $e);
				$time_group[] = array($s, $e);
			}
			foreach ( $coin_list as $coin_id ) {
				$key_list = [];
				foreach ( $time_group as $se ) {
					list( $s, $e ) = $se;
					$keySuf = "{$s}-{$e}:{$is_time}:{$is_feed}:";
					$keyMain = $keyPre.$keySuf;
					$key = $keyMain.$coin_id;
					$key_list[] = $this->SetRedisKey($key);
				}
				$article_list = $this->SetUnion($key_list);
				$coinArticleList[$coin_id] = $article_list ?:[];
			}
		}
		return is_array($coin_id_set) ? $coinArticleList : $coinArticleList[$coin_id_set];
	}
	
	//-----------------------------------------------每日非币种文章-----------------------------------------------------//
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}